﻿using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;

namespace AuthenticationCenter.Utility
{
    /// <summary>
    /// 选择加密方式 HS256 对称加密生成Token
    /// </summary>
    public class CustomDesJWTService : ICustomJWTService
    {

        private readonly JWTTokenOption JwtTokenOption;

        /// <summary>
        /// 构造函数注入 配置文件读取类后面用来读取配置文件
        /// </summary>
        /// <param name="jwtTokenOption"></param>
        public CustomDesJWTService(IOptionsMonitor<JWTTokenOption> jwtTokenOption)
        {
            JwtTokenOption = jwtTokenOption.CurrentValue;
        }


        /// <summary>
        /// 生成Token
        /// </summary>
        /// 
        /// 
        /// 
        /// <returns></returns>
        public string GetToken(string UserName,string NickName,int Sex,string Role)
        {
            #region 第一步装配有效载荷的数据
            //第一步 装配 有效载荷数据 尽量避免敏感信息 这里是传给鉴权端鉴权时使用的
            var claims = new[]
            {
               new Claim(ClaimTypes.Name, UserName),
               new Claim("NickName",NickName),//要传递给鉴权端的比如说昵称信息  
               new Claim("Role",Role),//要传递给鉴权端端的信息  
                new Claim("Sex",Sex.ToString()),//要传递给鉴权端的信息 
            };
            #endregion


            #region 第二步  生成 JwtSecurityToken 类
            //第二步 生成Token  

            //1.传入加密秘钥
            SymmetricSecurityKey key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(JwtTokenOption.SecurityKey));

            //2.选择加密方式 HS256
            //HS256(带有 SHA - 256 的 HMAC 是一种对称算法, 双方之间仅共享一个 密钥。由于使用相同的密钥生成签名和验证签名, 因此必须注意确保密钥不被泄密。
             SigningCredentials creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

            //3 通过构造函数方式 生成Token
            JwtSecurityToken token = new JwtSecurityToken(issuer: JwtTokenOption.Issuer,
                audience:JwtTokenOption.Audience,
                claims:claims,
                expires:DateTime.Now.AddMinutes(5),
                signingCredentials: creds
                );
            #endregion

            #region 第三步 将生成的  JwtSecurityToken类对象 传入 JwtSecurityTokenHandler.WriteToken()函数中生成Token字符串
            //装配 JwtSecurityToken 类这后调用   JwtSecurityTokenHandler.WriteToken 生成Token 字符串
            string returnToken = new JwtSecurityTokenHandler().WriteToken(token);
            #endregion

            return returnToken;
        }
    }
}
